﻿using System;
using System.Collections.Generic;
using System.IO;
using Commons.Collections;
using NVelocity;
using NVelocity.App;
using NVelocity.Context;

namespace BBCode.Template
{
    public class NVTemplate
    {
        private static readonly VelocityEngine engine = new VelocityEngine(new ExtendedProperties());
        private static bool initted;

        private static readonly Dictionary<string, byte[]> templates = new Dictionary<string, byte[]>();
        private readonly IContext context = new VelocityContext();
        private readonly string templatePath;

        /// <summary>
        /// Initializes a new instance of the <see cref="NVTemplate"/> class.
        /// </summary>
        /// <param name="templateName">Name of the template.</param>
        public NVTemplate(string templateName)
        {
            if (!initted)
            {
                engine.Init();
                initted = true;
            }
            context = new VelocityContext();

            var template = string.Format(@"{0}\{1}", Setting.AppSetting<string>("TemplateDirectory"), templateName);
            if (File.Exists(template))
            {
                templatePath = template;
            }
            else
            {
                //ErrorLogging.Write("NVTemplate", string.Format("Failed to load template file: {0}", template), null, LogType.Error);
                throw new ApplicationException("Failed to load template");
            }
        }

        /// <summary>
        /// Gets or sets the <see cref="System.Object"/> at the specified index.
        /// </summary>
        public object this[string index]
        {
            get { return context.Get(index); }
            set { context.Put(index, value); }
        }

        /// <summary>
        /// Processes this instance.
        /// </summary>
        /// <returns></returns>
        public string Process()
        {
            using (var writer = new StringWriter())
            {
                if (!templates.ContainsKey(templatePath))
                {
                    var fs = File.OpenRead(templatePath);
                    var b = new byte[fs.Length];
                    fs.Read(b, 0, b.Length);
                    fs.Close();

                    templates.Add(templatePath, b);
                }

                engine.Evaluate(context, writer, null, new StreamReader(new MemoryStream(templates[templatePath])));
                return writer.ToString();
            }
        }
    }
}